package com.rc.web.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.rc.common.constant.Code;
import com.rc.common.constant.RoleEnum;
import com.rc.common.exception.BusinessException;
import com.rc.common.util.SaltMD5Util;
import com.rc.pojo.dto.user.AddUserDTO;
import com.rc.pojo.dto.user.PageUserDTO;
import com.rc.pojo.dto.user.RestPasswordDTO;
import com.rc.pojo.dto.user.UserLoginDTO;
import com.rc.pojo.po.Farm;
import com.rc.pojo.po.User;
import com.rc.pojo.vo.user.UserLoginVO;
import com.rc.pojo.vo.user.UserPageVO;
import com.rc.pojo.vo.user.UserVO;
import com.rc.web.converter.UserConverter;
import com.rc.web.mapper.UserMapper;
import com.rc.web.service.FarmService;
import com.rc.web.service.UserService;
import io.swagger.annotations.ApiModelProperty;
import lombok.RequiredArgsConstructor;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.Range;
import org.springframework.stereotype.Service;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import java.io.Serializable;
import java.util.List;
import java.util.Map;


/**
 * 员工信息 服务层实现。
 *
 * @author sym
 * @since 2024-05-24
 */
/**
 * 用户服务实现类
 * 提供用户相关的业务逻辑实现
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    // 用户转换器
    private final UserConverter userConverter;
    // 农场服务
    private final FarmService farmService;

    /**
     * 添加用户
     * @param dto 用户添加DTO
     */
    @Override
    public void add(AddUserDTO dto) {
        // 检查用户名或手机号是否已存在
        var user = mapper.selectByUserNameOrPhone(dto.getUsername(),dto.getPhone());

        if (user != null){
            throw new BusinessException(Code.USER_EXISTED);
        }

        // 转换DTO为PO
        user = userConverter.addDTO2PO(dto);
        // 设置角色为员工
        user.setRole(RoleEnum.EMPLOYEE);

        // 使用MD5加密默认密码
        String md5Password = SaltMD5Util.generatePassword("123456");
        user.setPassword(md5Password);

        // 获取当前登录用户的农场ID
        var farmId = StpUtil.getSession().getModel("user", User.class).getFarmId();
        // 设置所属农场
        user.setFarmId(farmId);
        // 保存用户
        this.save(user);
    }

    /**
     * 用户登录
     * @param dto 用户登录DTO
     * @return 用户登录VO
     */
    @Override
    public UserLoginVO login(UserLoginDTO dto) {
        // 根据用户名或手机号查询用户
        var user = mapper.selectByUserNameOrPhone(dto.getUsername(),dto.getPhone());

        if (user == null){
            throw new BusinessException(Code.NO_SUCH_USER);
        }

        // 验证密码
        boolean equal = SaltMD5Util.verifyPassword(dto.getPassword(), user.getPassword());
        if (!equal){
            throw new BusinessException(Code.PASSWORD_ERROR);
        }

        // 登录并设置会话
        StpUtil.login(user.getId());
        StpUtil.getSession().set("user",user);

        // 构建返回VO
        var vo = userConverter.toLoginVO(user);
        var token = StpUtil.getTokenValue();
        vo.setToken(token);
        return vo;
    }

    @Override
    public UserVO getOneById(Long id) {
        var user = mapper.selectOneById(id);
        return userConverter.toVO(user);
    }

    @Override
    public List<UserVO> getList() {
        var loginInfo = StpUtil.getSession().getModel("user", User.class);
        var userList = mapper.selectAll();

        return switch (loginInfo.getRole()){
            case ADMIN -> userList.stream()
                    .filter(user -> user.getRole() == RoleEnum.FARM_ADMIN)
                    .map(userConverter::toVO)
                    .toList();

            case FARM_ADMIN-> userList.stream()
                    .filter(user -> user.getRole() == RoleEnum.EMPLOYEE)
                    .map(userConverter::toVO)
                    .toList();

            default -> throw new BusinessException(Code.ROLE_ERROR);
        };
    }

    @Override
    public Page<UserPageVO> getPage(PageUserDTO dto) {
        User loginInfo = StpUtil.getSession().getModel("user", User.class);
        if (loginInfo.getRole() == RoleEnum.FARM_ADMIN){
            dto.setRole(RoleEnum.EMPLOYEE);
        }
        dto.setUserId(loginInfo.getId());
        return mapper.selectPage(dto);
    }



    /**
     * 根据ID删除用户
     * @param id 用户ID
     */
    @Override
    public void deleteById(Long id) {
        // 获取要删除的用户
        User user = this.getById(id);

        // 如果用户是农场管理员，检查是否关联农场
        if (user != null && user.getRole() == RoleEnum.FARM_ADMIN){
            Farm farm = farmService.getById(user.getFarmId());
            if (farm != null){
                throw new BusinessException(Code.USER_HAS_FARM);
            }
        }

        // 删除用户
        boolean success = this.removeById(id);
        if (!success){
            throw new BusinessException(Code.NO_SUCH_USER);
        }

        // 删除成功后登出该用户
        StpUtil.logout(id);
    }

    /**
     * 重置用户密码
     * @param dto 重置密码DTO
     */
    @Override
    public void restPassword(RestPasswordDTO dto) {
        // 获取当前登录用户
        User user = StpUtil.getSession().getModel("user", User.class);

        // 加密新密码
        String password = SaltMD5Util.generatePassword(dto.getPassword());

        Long userId = dto.getId();

        // 根据角色执行不同的重置逻辑
        Boolean success = switch (user.getRole()) {
            case ADMIN,FARM_ADMIN -> mapper.resetPassword(password, userId);
            // 员工只能重置自己的密码
            case EMPLOYEE -> mapper.resetPassword(password, StpUtil.getLoginIdAsLong());
        };

        if (!success){
            throw new BusinessException(Code.NO_SUCH_USER);
        }

        // 修改密码后登出用户
        StpUtil.logout(userId);
    }

    /**
     * 获取农场管理员
     * @param farmId 农场ID
     * @return 农场管理员用户
     */
    @Override
    public User getFarmAdmin(Long farmId) {
        return mapper.selectFarmAdmin(farmId);
    }

    /**
     * 更新用户信息
     * @param dto 包含更新信息的Map
     */
    @Override
    public void restUser(Map<String, Object> dto) {
        // 获取用户ID
        String id = (String) dto.get("id");

        // 根据ID查询用户
        var user = mapper.selectOneById(id);

        // 更新用户信息
        user.setName((String) dto.get("name"));
        user.setUsername((String) dto.get("username"));
        user.setPhone((String) dto.get("phone"));
        if (((String) dto.get("sex")).equals("1")){
            user.setSex(1);
        }else {
            user.setSex(0);
        }
        user.setIdNumber((String) dto.get("idNumber"));

        // 保存更新
        this.updateById(user);
    }
}
